package com.ev.scm.service.impl;

import com.alibaba.fastjson.JSON;
import com.ev.custom.service.MaterielService;
import com.ev.framework.config.ConstantForGYL;
import com.ev.framework.il8n.MessageSourceHandler;
import com.ev.framework.utils.R;
import com.ev.scm.domain.DeliveryNoteItemDO;
import com.ev.scm.domain.SalescontractItemDO;
import com.ev.scm.domain.StockOutItemDO;
import com.ev.scm.service.*;
import com.google.common.collect.Maps;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class SaleStockOutServiceImpl extends StockOutServiceImpl implements SaleStockOutService {
    @Autowired
    private MessageSourceHandler messageSourceHandler;
    @Autowired
    private SalescontractItemService salescontractItemService;
    @Autowired
    private StockOutItemService stockOutItemService;
    @Autowired
    private StockInItemService stockInItemService;
    @Autowired
    private MaterielService materielService;
    @Autowired
    private IDeliveryNoteService iDeliveryNoteService;


    // 校验 发货通知 可执行数量
    @Override
    public R checkSourceNumberOfNotice(String item, Long id)  {
        List<StockOutItemDO> itemDOs = JSON.parseArray(item, StockOutItemDO.class);
        //合并数量及sourceId
        if(!CollectionUtils.isEmpty(itemDOs)){
            Map<Long, BigDecimal> countOfThis = itemDOs
                    .stream()
                    .filter(e -> e.getSourceId() != null)
                    .collect(Collectors.toMap(StockOutItemDO::getSourceId, StockOutItemDO::getCount, BigDecimal::add));
            List<Long> sourceIds = itemDOs.stream().map(e -> e.getSourceId()).collect(Collectors.toList());
            List<Long> materielIds = itemDOs.stream().map(e -> e.getMaterielId()).collect(Collectors.toList());

            Map<Long, String> materiels = materielService.getMaterielS(materielIds);
            List<DeliveryNoteItemDO> itemDetailByIds = iDeliveryNoteService.findItemDetailByIds(sourceIds);
            if(!CollectionUtils.isEmpty(itemDetailByIds)){
                for(DeliveryNoteItemDO aa:itemDetailByIds) {
                    BigDecimal executableCount = aa.getExecutableCount()==null?BigDecimal.ZERO:aa.getExecutableCount();
                    BigDecimal deliveryCount = aa.getDeliveryCount()==null?BigDecimal.ZERO:aa.getDeliveryCount();
                    BigDecimal vule = deliveryCount.subtract(executableCount);
                    if (countOfThis.containsKey(aa.getId())) {
                        BigDecimal count = countOfThis.get(aa.getId());
                        if(count.compareTo(vule)>0){
                            String msg = materiels.get(aa.getMaterielId()) +" 发货数量已将超过发货通知数量！操作失败";
                            return R.error(500,msg);
                        }
                    }
                }
            }
        }
        return null;
    }


   @Override
    public R checkSourceNumber(String item,Long id) {
        // 与源单数量对比
        List<StockOutItemDO> itemDOs = JSON.parseArray(item, StockOutItemDO.class);
        //合并数量及sourceId
        Map<Long, BigDecimal> count = itemDOs
                .stream()
                .filter(e -> e.getSourceId() != null)
                .collect(Collectors.toMap(StockOutItemDO::getSourceId, StockOutItemDO::getCount, BigDecimal::add));

        // 获取原先单据的数量
        Map<Long, BigDecimal> oldCounts = Maps.newHashMap();
        if (id != null) {
            Map<String,Object> map = Maps.newHashMap();
            map.put("outId",id);
            List<StockOutItemDO> list = stockOutItemService.list(map);
            if (list.size() > 0) {
                oldCounts = list.stream()
                        .collect(Collectors.toMap(StockOutItemDO::getSourceId, StockOutItemDO::getCount, BigDecimal::add));
            }
        }

        SalescontractItemDO detailDO;
        BigDecimal contractCount;
        BigDecimal returnCount;
        if (count.size() > 0) {
            for (Long sourceId : count.keySet()) {
                detailDO = salescontractItemService.get(sourceId);
                contractCount = detailDO.getCount();
                // 查询源单已被选择数量
                Map<String,Object> map = Maps.newHashMap();
                map.put("sourceId",sourceId);
                map.put("sourceType",ConstantForGYL.XSHT);
                BigDecimal bySource = stockOutItemService.getCountBySource(map);

                BigDecimal oldCount = oldCounts.getOrDefault(sourceId,BigDecimal.ZERO);

                BigDecimal countByOutSource = bySource == null ? BigDecimal.ZERO : bySource.subtract(oldCount);
                map.put("returnSourceType", ConstantForGYL.XSCK);
                returnCount = stockInItemService.getReturnCountBySource(map);
                if (returnCount != null) {
                    countByOutSource = countByOutSource.subtract(returnCount);
                }

                if (contractCount.compareTo(count.get(sourceId).add(countByOutSource))<0){
                List<StockOutItemDO> collect = itemDOs.stream()
                        .filter(itemDO -> Objects.equals(itemDO.getSourceId(),sourceId))
                        .collect(Collectors.toList());
                String sourceCount = contractCount.subtract(countByOutSource).stripTrailingZeros().toPlainString();
                String [] args = {count.get(sourceId).stripTrailingZeros().toPlainString(),sourceCount,collect.get(0).getSourceCode()};
                Map<String,Object> result = Maps.newHashMap();
                result.put("sourceId",sourceId);
                result.put("sourceCount",sourceCount);
                return R.error(500,messageSourceHandler.getMessage("stock.number.error", args),result);
            }
        }
        }
        return null;
    }

    @Override
    public R reverseAuditSaleStockOut(Long id) {
        if (this.childCount(id) >0 ) {
            return R.error(messageSourceHandler.getMessage("scm.childList.reverseAudit", null));
        }
        R audit = this.reverseAuditForR(id, ConstantForGYL.XSCK);
        return audit==null?R.ok():audit;
    }


}
